package edu.zut.main.thread;

public class ThreadCommunication {

    public static void main(String[] args) {
        Stack stack = new Stack();
        new Thread(() -> {
            for (int i = 0; i < 20; i++) {
                char c =(char) (Math.random()*26 + 'a');
                stack.push(c);
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

        },"生产者").start();

        new Thread(() -> {
            for (int i = 0; i < 20; i++) {
                char c = stack.pop();
                try {
                    Thread.sleep(300);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"消费者").start();

    }

}
/**
 * 线程通信：生产者与消费者问题
 *  生产者：负责生产产品，如果库存满了，停止生产（生产者由生产转为等待），如果消费者唤醒生产者，
 *          那么就接着生产。
 *  消费者：负责消费，每消费一次，生产者的库存会-1，当消费者，将生产者生产的产品全部消费完，
 *      此时我们消费者需要将生产者唤醒，消费者转为等待
 */

//堆
class Stack{
    //模拟为下标   每次往仓库中添加一个数据，point+1
    private int point = 0;
    //data模拟为仓库
    private char[] data = new char[5];


    //往仓库中放入数据
    public synchronized void push(char c){
        while (point == data.length){
            //如果数据满了，我们让当前操作等待
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        //往仓库中放入数据的同时可以唤醒消费者，进行消费
        this.notifyAll();
        System.out.println("生产了：" + c);
        data[point] = c;
        point ++;
    }


    //往仓库外取
    public synchronized char pop(){
        //如果point为0，表示无数据，此时消费者等待
        while (point == 0){
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        //消费者只要消费了数据，就可以唤醒生产者生产数据
        this.notifyAll();
        point --;
        System.out.println("消费了：" + data[point]);
        return data[point];
    }



}

